home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 101-125 / 118 / empire / src / source.zoo / scan.d < prev    next >
Text File  |  1987-12-02  |  15KB  |  669 lines

  1. #empire.g
  2. #empfunc.g
  3.  
  4. uint
  5.     MAX_CONDITIONS = 8,         /* max # '?' conditions */
  6.     MAX_SHIPS = 32;            /* max # specific ships */
  7.  
  8. /* negative codes for a unit to be compared: */
  9.  
  10. int
  11.     U_EFFICIENCY    = -1,
  12.     U_MOBILITY        = -2,
  13.     U_DEFENDED        = -3,
  14.     U_MILITARY        = -4,
  15.     U_PLANES        = -5,
  16.     U_MINERALS        = -6,
  17.     U_PRODUCTION    = -7,
  18.     U_CONTRACTED    = -8,
  19.     U_SHELLS        = -9,
  20.     U_ORE        = -10,
  21.     U_GOLD        = -11,
  22.     U_CHECKPOINT    = -12,
  23.     U_CIVILIANS     = -13,
  24.     U_GUNS        = -14,
  25.     U_BARS        = -15,
  26.     U_DESIGNATION    = -16,
  27.     U_OWNER        = -17;
  28.  
  29. *char UNITS =
  30.     "efficiency\e"
  31.     "mobility\e"
  32.     "defended\e"
  33.     "military\e"
  34.     "planes\e"
  35.     "minerals\e"
  36.     "production\e"
  37.     "contracted\e"
  38.     "shells\e"
  39.     "ore\e"
  40.     "gold\e"
  41.     "checkpoint\e"
  42.     "civilians\e"
  43.     "guns\e"
  44.     "bars\e"
  45.     "designation\e"
  46.     "owner\e";
  47.  
  48. type
  49.     Condition_t = struct {
  50.     int c_left;
  51.     char c_operator;
  52.     int c_right;
  53.     },
  54.  
  55.     ShipPattern_t = enum {
  56.     shp_none,                /* no conditions */
  57.     shp_list,                /* list of ship numbers */
  58.     shp_box,                /* sectors they are in */
  59.     shp_fleet                /* a fleet they are in */
  60.     };
  61.  
  62. uint ConditionCount;
  63. [MAX_CONDITIONS] Condition_t Condition;
  64. int BoxTop, BoxBottom, BoxLeft, BoxRight;
  65.  
  66. Sector_t CurrentSector;
  67. bool MapHook;
  68.  
  69. ShipPattern_t ShipPatternType;
  70. uint ShipCount;
  71. [MAX_SHIPS] uint ShipList;
  72. char ShipFleet;
  73. Ship_t CurrentShip;
  74.  
  75. /*
  76.  * member -
  77.  *    return true if character is in string
  78.  */
  79.  
  80. proc member(*char set; char element)bool:
  81.  
  82.     while set* ~= '\e' and set* ~= element do
  83.     set := set + sizeof(char);
  84.     od;
  85.     set* = element
  86. corp;
  87.  
  88. /*
  89.  * getValue -
  90.  *    get a value for a condition.
  91.  */
  92.  
  93. proc getValue(bool isRight, isShip)bool:
  94.     *char p;
  95.     uint res;
  96.     int valu;
  97.     char ch;
  98.     bool ok;
  99.  
  100.     ok := true;
  101.     if InputPtr* >= '0' and InputPtr* <= '9' then
  102.     /* a simple numeric value */
  103.     valu := 0;
  104.     while InputPtr* >= '0' and InputPtr* <= '9' do
  105.         valu := valu * 10 + (InputPtr* - '0');
  106.         InputPtr := InputPtr + 1;
  107.     od;
  108.     elif (InputPtr + 1)* < 'a' or (InputPtr + 1)* > 'z' then
  109.     /* assume its a one-character designation character */
  110.     ch := InputPtr*;
  111.     InputPtr := InputPtr + 1;
  112.     if isShip then
  113.         if not member(&ShipChar[0], ch) then
  114.         err("invalid ship designation in condition");
  115.         ok := false;
  116.         else
  117.         valu := getIndex(&ShipChar[0], ch);
  118.         fi;
  119.     else
  120.         if not member(&SectorChar[0], ch) then
  121.         err("invalid sector designation in condition");
  122.         ok := false;
  123.         else
  124.         valu := getIndex(&SectorChar[0], ch);
  125.         fi;
  126.     fi;
  127.     else
  128.     p := InputPtr;
  129.     while InputPtr* >= 'a' and InputPtr* <= 'z' do
  130.         InputPtr := InputPtr + sizeof(char);
  131.     od;
  132.     ch := InputPtr*;
  133.     InputPtr* := '\e';
  134.     res := lookupCommand(UNITS, p);
  135.     if res = 0 then
  136.         err("invalid unit in condition");
  137.         ok := false;
  138.     elif res = 1 then
  139.         err("ambiguous unit in condition");
  140.         ok := false;
  141.     else
  142.         InputPtr* := ch;
  143.         valu := 1 - make(res, int);
  144.     fi;
  145.     fi;
  146.     if ok then
  147.     if isRight then
  148.         Condition[ConditionCount].c_right := valu;
  149.     else
  150.         Condition[ConditionCount].c_left := valu;
  151.     fi;
  152.     fi;
  153.     ok
  154. corp;
  155.  
  156. /*
  157.  * getOperator -
  158.  *    get a valid condition operator.
  159.  */
  160.  
  161. proc getOperator()bool:
  162.  
  163.     if InputPtr* = '<' or InputPtr* = '>' or InputPtr* = '=' or
  164.         InputPtr* = '\#' then
  165.     Condition[ConditionCount].c_operator := InputPtr*;
  166.     InputPtr := InputPtr + 1;
  167.     true
  168.     else
  169.     err("invalid operator in condition");
  170.     false
  171.     fi
  172. corp;
  173.  
  174. /*
  175.  * parseConditions -
  176.  *    parse a set of conditions from the command line, and store them into
  177.  *    the condition array. 'isShip' is true if we want conditions that will
  178.  *    apply to ship (some limitations). We return 'true' if all went well.
  179.  */
  180.  
  181. proc parseConditions(bool isShip)bool:
  182.     char operator, desig;
  183.     bool done, hadError;
  184.  
  185.     if InputPtr* = '/' then
  186.     /* special case, allow '/x' to mean '?des=x' */
  187.     InputPtr := InputPtr + 1;
  188.     ConditionCount := 0;
  189.     Condition[0].c_left := U_DESIGNATION;
  190.     Condition[0].c_operator := '=';
  191.     if getValue(true, isShip) then
  192.         if Condition[0].c_right < 0 then
  193.         err("must use designation letter with '/'");
  194.         false
  195.         else
  196.         ConditionCount := 1;
  197.         true
  198.         fi
  199.     else
  200.         false
  201.     fi
  202.     else
  203.     ConditionCount := 0;
  204.     if InputPtr* = '?' then
  205.         InputPtr := InputPtr + 1;
  206.         done := false;
  207.         hadError := false;
  208.         while not done and not hadError do
  209.         if InputPtr* = '\e' or InputPtr* = ' ' or InputPtr* = '\t' then
  210.             /* no more conditions */
  211.             done := true;
  212.         elif ConditionCount = MAX_CONDITIONS then
  213.             err("too many conditions");
  214.             hadError := true;
  215.         elif getValue(false, isShip) and
  216.             getOperator() and
  217.             getValue(true, isShip) then
  218.             if Condition[ConditionCount].c_left = U_DESIGNATION and
  219.                 Condition[ConditionCount].c_right < 0 or
  220.                 Condition[ConditionCount].c_right = U_DESIGNATION
  221.                 and Condition[ConditionCount].c_left < 0 then
  222.             err("invalid use of designation character");
  223.             hadError := true;
  224.             elif Condition[ConditionCount].c_left >= 0 and
  225.                 Condition[ConditionCount].c_right >= 0 then
  226.             err("invalid condition - no field");
  227.             hadError := true;
  228.             else
  229.             ConditionCount := ConditionCount + 1;
  230.             if InputPtr* = '&' then
  231.                 InputPtr := InputPtr + sizeof(char);
  232.             elif InputPtr* ~= '\e' and InputPtr* ~= ' ' and
  233.                 InputPtr* ~= '\t' then
  234.                 err("syntax error in conditions");
  235.                 hadError := true;
  236.             fi;
  237.             fi;
  238.         else
  239.             hadError := true;
  240.         fi;
  241.         od;
  242.         not hadError
  243.     else
  244.         true
  245.     fi
  246.     fi
  247. corp;
  248.  
  249. /*
  250.  * getShips -
  251.  *    get a ships specifier
  252.  */
  253.  
  254. proc getShips()bool:
  255.     *char p;
  256.     uint shipNumber;
  257.     bool hadError, done;
  258.  
  259.     if InputPtr* = '?' or InputPtr* = '/' then
  260.     ShipPatternType := shp_none;
  261.     parseConditions(true)
  262.     elif InputPtr* = '*' or InputPtr* >= 'a' and InputPtr* <= 'z' or
  263.         InputPtr* >= 'A' and InputPtr* <= 'Z' then
  264.     ShipPatternType := shp_fleet;
  265.     ShipFleet := InputPtr*;
  266.     InputPtr := InputPtr + sizeof(char);
  267.     parseConditions(true)
  268.     elif InputPtr* = '-' or InputPtr* = '\#' then
  269.     ShipPatternType := shp_box;
  270.     getBox(&BoxTop, &BoxBottom, &BoxLeft, &BoxRight) and
  271.         parseConditions(true)
  272.     elif InputPtr* < '0' or InputPtr* > '9' then
  273.     err("invalid ships specification");
  274.     false
  275.     else
  276.     p := InputPtr;
  277.     while p* >= '0' and p* <= '9' do
  278.         p := p + 1;
  279.     od;
  280.     if p* = ',' or p* = ':' then
  281.         ShipPatternType := shp_box;
  282.         getBox(&BoxTop, &BoxBottom, &BoxLeft, &BoxRight) and
  283.         parseConditions(true)
  284.     else
  285.         /* we have a list of ship numbers separated by '/'s */
  286.         ShipPatternType := shp_list;
  287.         ShipCount := 0;
  288.         hadError := false;
  289.         done := false;
  290.         while not done and not hadError do
  291.         if ShipCount = MAX_SHIPS then
  292.             err("too many ships listed");
  293.             hadError := true;
  294.         elif InputPtr* < '0' or InputPtr* > '9' then
  295.             err("invalid ship number");
  296.             hadError := true;
  297.         else
  298.             shipNumber := 0;
  299.             while InputPtr* >= '0' and InputPtr* <= '9' do
  300.             shipNumber := shipNumber * 10 + (InputPtr* - '0');
  301.             InputPtr := InputPtr + sizeof(char);
  302.             od;
  303.             if shipNumber >= World.w_shipNext then
  304.             err("ship number too big");
  305.             hadError := true;
  306.             fi;
  307.             ShipList[ShipCount] := shipNumber;
  308.             ShipCount := ShipCount + 1;
  309.             if InputPtr* = '/' then
  310.             InputPtr := InputPtr + sizeof(char);
  311.             elif InputPtr* = '\e' or InputPtr* = '?' or
  312.                 InputPtr* = ' ' or InputPtr* = '\t' then
  313.             done := true;
  314.             else
  315.             err("invalid character in ship list");
  316.             hadError := true;
  317.             fi;
  318.         fi;
  319.         od;
  320.         not hadError and parseConditions(true)
  321.     fi
  322.     fi
  323. corp;
  324.  
  325. /*
  326.  * setAllShips -
  327.  *    special entry point so cmd_ships can request all ships
  328.  */
  329.  
  330. proc setAllShips()void:
  331.  
  332.     ShipPatternType := shp_none;
  333.     ConditionCount := 0;
  334. corp;
  335.  
  336. /*
  337.  * reqShips - request/get a ships list
  338.  */
  339.  
  340. proc reqShips(*char prompt)bool:
  341.     bool gotOne;
  342.  
  343.     if InputPtr* = '\e' then
  344.     gotOne := true;
  345.     while
  346.         write(PromptOut; prompt);
  347.         if not readLine(&InputBuffer[0], INPUT_LENGTH) or
  348.             InputBuffer[0] = '\e' then
  349.         pretend(ioerror(Chin), void);
  350.         gotOne := false;
  351.         false
  352.         else
  353.         InputPtr := &InputBuffer[0];
  354.         skipBlanks();
  355.         not getShips()
  356.         fi
  357.     do
  358.     od;
  359.     gotOne
  360.     else
  361.     getShips()
  362.     fi
  363. corp;
  364.  
  365. /*
  366.  * getConditionValue -
  367.  *    return the int giving the appropriate value for a condition.
  368.  */
  369.  
  370. proc getConditionValue(int valu; bool isShip)int:
  371.  
  372.     if valu >= 0 then
  373.     valu
  374.     else
  375.     if isShip then
  376.         case valu
  377.         incase U_CIVILIANS:
  378.         incase U_MILITARY:
  379.         make(CurrentShip.sh_crew, int)
  380.         incase U_SHELLS:
  381.         CurrentShip.sh_shells
  382.         incase U_GUNS:
  383.         CurrentShip.sh_guns
  384.         incase U_PLANES:
  385.         CurrentShip.sh_planes
  386.         incase U_ORE:
  387.         CurrentShip.sh_ore
  388.         incase U_BARS:
  389.         CurrentShip.sh_bars
  390.         incase U_DESIGNATION:
  391.         CurrentShip.sh_type - st_first
  392.         incase U_EFFICIENCY:
  393.         CurrentShip.sh_efficiency
  394.         incase U_MOBILITY:
  395.         CurrentShip.sh_mobility
  396.         incase U_OWNER:
  397.         CurrentShip.sh_owner
  398.         default:
  399.         err("unknown ship unit");
  400.         0
  401.         esac
  402.     else
  403.         case valu
  404.         incase U_EFFICIENCY:
  405.         make(CurrentSector.s_efficiency, int)
  406.         incase U_MOBILITY:
  407.         CurrentSector.s_mobility
  408.         incase U_DEFENDED:
  409.         if CurrentSector.s_defender = NO_DEFEND then
  410.             0
  411.         else
  412.             1
  413.         fi
  414.         incase U_MILITARY:
  415.         readQuan(CurrentSector, it_military)
  416.         incase U_PLANES:
  417.         readQuan(CurrentSector, it_planes)
  418.         incase U_MINERALS:
  419.         CurrentSector.s_iron
  420.         incase U_PRODUCTION:
  421.         CurrentSector.s_production
  422.         incase U_CONTRACTED:
  423.         if CurrentSector.s_price ~= 0 then
  424.             1
  425.         else
  426.             0
  427.         fi
  428.         incase U_SHELLS:
  429.         readQuan(CurrentSector, it_shells)
  430.         incase U_ORE:
  431.         readQuan(CurrentSector, it_ore)
  432.         incase U_GOLD:
  433.         CurrentSector.s_gold
  434.         incase U_CHECKPOINT:
  435.         CurrentSector.s_checkPoint
  436.         incase U_CIVILIANS:
  437.         readQuan(CurrentSector, it_civilians)
  438.         incase U_GUNS:
  439.         readQuan(CurrentSector, it_guns)
  440.         incase U_BARS:
  441.         readQuan(CurrentSector, it_bars)
  442.         incase U_DESIGNATION:
  443.         CurrentSector.s_type - s_first
  444.         incase U_OWNER:
  445.         CurrentSector.s_owner
  446.         default:
  447.         err("unknown sector unit");
  448.         0
  449.         esac
  450.     fi
  451.     fi
  452. corp;
  453.  
  454. /*
  455.  * checkConditions -
  456.  *    see if the setup conditions match the current ship/sector
  457.  */
  458.  
  459. proc checkConditions(bool isShip)bool:
  460.     uint condition;
  461.     int left, right;
  462.     bool matching;
  463.  
  464.     matching := true;
  465.     condition := 0;
  466.     while condition ~= ConditionCount and matching do
  467.     left  := getConditionValue(Condition[condition].c_left , isShip);
  468.     right := getConditionValue(Condition[condition].c_right, isShip);
  469.     matching :=
  470.         case Condition[condition].c_operator
  471.         incase '<':
  472.         left < right
  473.         incase '>':
  474.         left > right
  475.         incase '=':
  476.         left = right
  477.         incase '\#':
  478.         left ~= right
  479.         esac;
  480.     condition := condition + 1;
  481.     od;
  482.     matching
  483. corp;
  484.  
  485. /*
  486.  * scanShips -
  487.  *    The actual ship scanning routine. It calls its argument proc
  488.  *    for each ship that meets the set up specs and conditions.
  489.  */
  490.  
  491. proc scanShips(proc(uint shipNumber; Ship_t sh)void scanner)uint:
  492.     Fleet_t fleet;
  493.     uint shipNumber, i, count;
  494.     int r, c;
  495.  
  496.     count := 0;
  497.     if World.w_shipNext ~= 0 then
  498.     if ShipPatternType = shp_list then
  499.         i := 0;
  500.         while i ~= ShipCount and not gotControlC() do
  501.         shipNumber := ShipList[i];
  502.         readShip(shipNumber, CurrentShip);
  503.         if CurrentShip.sh_owner = ThisCountryNumber or
  504.             ThisCountryNumber = DEITY then
  505.             if checkConditions(true) then
  506.             count := count + 1;
  507.             scanner(shipNumber, CurrentShip);
  508.             fi;
  509.         fi;
  510.         i := i + 1;
  511.         od;
  512.     elif ShipPatternType = shp_fleet and ShipFleet ~= '*' then
  513.         if ThisCountry*.c_fleets[fleetPos(ShipFleet)] = NO_FLEET then
  514.         err("you have no such fleet");
  515.         else
  516.         readFleet(ThisCountry*.c_fleets[fleetPos(ShipFleet)], fleet);
  517.         if fleet.f_count = 0 then
  518.             err("fleet has no ships");
  519.         else
  520.             i := 0;
  521.             while i ~= fleet.f_count and not gotControlC() do
  522.             readShip(fleet.f_ship[i], CurrentShip);
  523.             if checkConditions(true) then
  524.                 count := count + 1;
  525.                 scanner(fleet.f_ship[i], CurrentShip);
  526.             fi;
  527.             i := i + 1;
  528.             od;
  529.         fi;
  530.         fi;
  531.     else
  532.         shipNumber := 0;
  533.         while shipNumber ~= World.w_shipNext and not gotControlC() do
  534.         readShip(shipNumber, CurrentShip);
  535.         if CurrentShip.sh_owner = ThisCountryNumber or
  536.             ThisCountryNumber = DEITY then
  537.             if
  538.             case ShipPatternType
  539.             incase shp_none:
  540.                 true
  541.             incase shp_box:
  542.                 r := unTransRow(ThisCountryNumber,
  543.                         CurrentShip.sh_row);
  544.                 c := unTransCol(ThisCountryNumber,
  545.                         CurrentShip.sh_col);
  546.                 r >= BoxTop and r <= BoxBottom and
  547.                 c >= BoxLeft and c <= BoxRight
  548.             incase shp_fleet:    /* '*' fleet */
  549.                 CurrentShip.sh_fleet = ShipFleet
  550.             esac
  551.             then
  552.             if checkConditions(true) then
  553.                 count := count + 1;
  554.                 scanner(shipNumber, CurrentShip);
  555.             fi;
  556.             fi;
  557.         fi;
  558.         shipNumber := shipNumber + 1;
  559.         od;
  560.     fi;
  561.     fi;
  562.     count
  563. corp;
  564.  
  565. /*
  566.  * getSectors -
  567.  *    get a sectors specifier
  568.  */
  569.  
  570. proc getSectors()bool:
  571.  
  572.     getBox(&BoxTop, &BoxBottom, &BoxLeft, &BoxRight) and
  573.         parseConditions(false)
  574. corp;
  575.  
  576. /*
  577.  * reqSectors - request/get a sectors specification
  578.  */
  579.  
  580. proc reqSectors(*char prompt)bool:
  581.     bool gotOne;
  582.  
  583.     MapHook := false;
  584.     if InputPtr* = '\e' then
  585.     gotOne := true;
  586.     while
  587.         write(PromptOut; prompt);
  588.         if not readLine(&InputBuffer[0], INPUT_LENGTH) or
  589.             InputBuffer[0] = '\e' then
  590.         pretend(ioerror(Chin), void);
  591.         gotOne := false;
  592.         false
  593.         else
  594.         InputPtr := &InputBuffer[0];
  595.         skipBlanks();
  596.         not getSectors()
  597.         fi
  598.     do
  599.     od;
  600.     gotOne
  601.     else
  602.     getSectors()
  603.     fi
  604. corp;
  605.  
  606. /*
  607.  * setMapHook - set the special flag for map generation.
  608.  */
  609.  
  610. proc setMapHook()void:
  611.  
  612.     MapHook := true;
  613. corp;
  614.  
  615. /*
  616.  * scanSectors -
  617.  *    The actual sector scanning routine. It calls its argument proc
  618.  *    for each sector that meets the set up specs and conditions.
  619.  */
  620.  
  621. proc scanSectors(proc(int row, col; Sector_t s)void scanner)uint:
  622.     uint count;
  623.     int r, c;
  624.     bool aborted;
  625.  
  626.     count := 0;
  627.     if MapHook then
  628.     mapCoords(BoxLeft, BoxRight);
  629.     writeln(Chout;);
  630.     fi;
  631.     aborted := false;
  632.     r := BoxTop;
  633.     while r <= BoxBottom and not aborted do
  634.     if MapHook then
  635.         mapRowStart(r);
  636.     fi;
  637.     c := BoxLeft;
  638.     while c <= BoxRight and not aborted do
  639.         accessSector(r, c, CurrentSector);
  640.         if ThisCountryNumber = DEITY or
  641.             CurrentSector.s_owner = ThisCountryNumber or
  642.             MapHook and ConditionCount = 0 then
  643.         if checkConditions(false) then
  644.             count := count + 1;
  645.             scanner(r, c, CurrentSector);
  646.         elif MapHook then
  647.             mapEmpty();
  648.         fi;
  649.         elif MapHook then
  650.         mapEmpty();
  651.         fi;
  652.         c := c + 1;
  653.         aborted := gotControlC();
  654.     od;
  655.     if MapHook and not aborted then
  656.         mapRowEnd(r);
  657.     fi;
  658.     r := r + 1;
  659.     if gotControlC() then
  660.         aborted := true;
  661.     fi;
  662.     od;
  663.     if MapHook and not aborted then
  664.     writeln(Chout;);
  665.     mapCoords(BoxLeft, BoxRight);
  666.     fi;
  667.     count
  668. corp;
  669.